package com.example.demo.grpc.utils;

import com.example.demo.Request;
import com.example.demo.Response;
import com.google.protobuf.Any;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ls
 * @description 报文解析工具
 * @date 2025/6/5 18:20
 */
public class MsgParse {
    //报文类型class 缓存
    private static final Map<String, Class<? extends Message>> TYPE_REGISTRY =  new ConcurrentHashMap<>();

    /**
     * 解析请求体
     * @param request 请求
     * @return 请求体
     * @throws InvalidProtocolBufferException 解析异常
     * @throws ClassNotFoundException 类不存在异常
     */
    public static <T extends Message> T parseReqBody(Request request) throws InvalidProtocolBufferException, ClassNotFoundException {
        if (request.hasBody()) {
            Any body = request.getBody();
            return body.unpack(getType(body));
        }
        return null;
    }
    /**
     * 解析响应体
     * @param response 响应
     * @return 响应体
     * @throws InvalidProtocolBufferException 解析异常
     * @throws ClassNotFoundException 类不存在异常
     */
    public static <T extends Message> T parseResBody(Response response) throws InvalidProtocolBufferException, ClassNotFoundException {
        if (response.hasBody()) {
            Any body = response.getBody();
            return body.unpack(getType(body));
        }
        return null;
    }

    /**
     * 获取报文类型
     * @param data 报文
     * @return 报文类型
     * @throws ClassNotFoundException 类不存在异常
     */
    private static <T extends Message> Class<T>  getType(Any data) throws  ClassNotFoundException {
        String fullType = data.getTypeUrl();
        String className = fullType.substring(fullType.lastIndexOf("/") + 1);
        Class<? extends Message> clazz = TYPE_REGISTRY.get(className);
        if (clazz != null) {
            return (Class<T>) clazz;
        }
        Class<T> newClazz = (Class<T>) Class.forName(className);
        TYPE_REGISTRY.put(className,newClazz );
        return newClazz;
    }
}
